package erfgame.frontend.desktop.view.terrain.iso.handler;

import java.awt.Point;
import java.util.HashSet;
import java.util.List;

import erfgame.core.Point3D;
import erfgame.core.Point3DAndRotation;
import erfgame.core.dao.ObjectDAO;
import erfgame.core.entity.Entity;
import erfgame.core.entity.Physical;
import erfgame.core.graph.simple.Node;
import erfgame.core.graphics.renderer.chain.RendererChain;
import erfgame.core.world.World;
import erfgame.core.world.terrain.BlockSurfaceImages;
import erfgame.core.world.terrain.GridRectangle;
import erfgame.core.world.terrain.TerrainUtils;
import erfgame.core.world.terrain.insertion.SurfaceInsertion;

import erfgame.frontend.desktop.view.terrain.iso.EntitySelection;
import erfgame.frontend.desktop.view.terrain.iso.IsometricTerrainView;

public class EntitySelectionGridSelectionAction 
	implements GridSelectionAction {
	private IsometricTerrainView view;
	private EntitySelection selection;
	
	public EntitySelectionGridSelectionAction( IsometricTerrainView view, EntitySelection selection  ) {
		this.view = view;
		this.selection = selection;
	}

	public void select(GridRectangle rectangle, int minbz, int maxbz) {
		World world = view.getCurrentWorld();
		this.selection.clear();
		
		List<Point> area = rectangle.getArea();
		HashSet<Point> blocks = new HashSet<Point>();
		for( int i=area.size(); i>0; ) {
			i--;
			Point grid = area.get(i);
			int bx = grid.x >> world.getxGridTilesPerBlockShift();
			int by = grid.y >> world.getyGridTilesPerBlockShift();
			// TODO corner cases
			if( bx >= 0 && by >= 0 && bx < world.getBlocksX() && by < world.getBlocksY() ) {
				Point block = new Point( bx, by );
				blocks.add( block );
			}
		}
		
		ObjectDAO<Point3DAndRotation, BlockSurfaceImages>  bsiDAO;
		bsiDAO = view.getSurfaceImagesDAO();
		
		for( Point b : blocks ) {
			for( int bz = minbz; bz<=maxbz; bz++ ) {
				Point3DAndRotation p = new Point3DAndRotation(b.x, b.y, bz, view.getCurrentRotation() );
				BlockSurfaceImages bsis = bsiDAO.retrieveObject(p);
				List<Node<SurfaceInsertion>> insertions = bsis.getSurfaceInsertions();
				for( int i=insertions.size(); i>0; ) {
					i--;
					SurfaceInsertion insertion = insertions.get(i).getValue();
					RendererChain rendererChain = insertion.getRendererChain();
					Entity entity = rendererChain.getHead().getEntity();
					if( entity != null && entity instanceof Physical ) {
						Point3D position = ((Physical)entity).getPosition();
						// see if they are in the grids
						Point g = world.getGridCoordinates(position.x, position.y);
						if( area.contains(g) ) {
							selection.addRendererChain( rendererChain, view.getCurrentRotation() );
						}
					}
				}
			}
		}
	}
}
